//
// Created by Immortal on 4/23/2021.
//

#ifndef RACOON_SERVER_H
#define RACOON_SERVER_H
#include "Http.h"

#define _LINUX_PLATFORM_
//#define _WINDOWS_PLATFORM_

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <map>
#include <queue>


#ifdef _LINUX_PLATFORM_
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <netinet/in.h>
#include <sys/sysinfo.h>
#include <signal.h>

#elif _WINDOWS_PLATFORM_
#include <windows.h>
#include <winsock2.h>
#endif

class Server
{
public:
    typedef void (*PHANDLINGFUNC)(void*, void*);
public:
    //目前的数据状态
    enum _DATA_STATUS
    {
        //错误
        DS_ERROR = 0,
        //读取头
        DS_READ_HEAD,
        //读取内容
        DS_READ_CONTENT,
        //处理数据
        DS_HANDLING,
        //写头
        DS_WRITE_HEAD,
        //写内容
        DS_WRITE_CONTENT,
        //写文件
        DS_WRITE_FILE,
        //完成
        DS_FINISH

    }DATA_STATUS;

public:
    //数据 -- 已接收 待发送 的数据都存储在这个结构里
    typedef struct _DATA
    {
        //描述符
        int cfd;
        //客户端信息
        sockaddr_in CliAddr;

        //请求头
        std::string strReqHead;
        //请求内容
        std::string strReqContent;

        //响应头
        std::string strResHead;
        //响应内容
        std::string strResContent;
        //已发送响应头数据
        int nSentHead;
        //已发送响应头内容
        int nSentContent;

        //数据状态
        Server::_DATA_STATUS ds;
        //http
        Http http;

    }DATA, *PDATA;
public:
    Server(uint16_t uPort);
    ~Server();

public:
    //初始化socket
    bool InitSocket(uint16_t uPort);

    //设置非阻塞
    bool SetNonBlock(int cfd);

    //设置处理函数
    void SetHandlingFunc(PHANDLINGFUNC pHandlingFunc, void* pArg);

    //执行
    bool Exec();

    //设置请求头最大限制
    void SetReqHeadLimit(int nSize);
    //设置请求内容最大限制
    void SetReqContentLimit(int nSize);

private:
    //接受客户端
    bool AcceptCli();
    //处理客户端
    bool HandlingCli(int cfd);

public:
    //修改epoll中的fd
    static bool CtlFd(int epfd, int op, int fd, uint32_t events);
    //工作者线程
    static void WorkerProc(Server* pServer);

    //数据错误
    static void DataError(Server* pServer, Server::PDATA pData);
    //读取数据
    static int ReadData(int epfd, int cfd, char* buf, int n, bool& bIsErr);
    //读取请求头
    static void ReadHead(Server* pServer, Server::PDATA pData);
    //读取内容
    static void ReadContent(Server* pServer, Server::PDATA pData);


    //发送数据
    static int SendData(int epfd, int cfd, const char* buf, int n, bool& bIsErr);
    //发送数据
    static bool SendData(int epfd, int cfd, std::string& strResData, int* pSentData, bool& bIsErr);
    //发送请求头
    static void SendHead(Server* pServer, Server::PDATA pData);
    //发送内容
    static void SendContent(Server* pServer, Server::PDATA pData);
    //发送文件
    static void SendFile(Server* pServer, Server::PDATA pData);
    //响应完成
    static void ResFinish(Server* pServer, Server::PDATA pData);

private:
    //基础
    int m_epfd;
    int m_lfd;
    sockaddr_in m_SvrAddr;

    //处理函数
    PHANDLINGFUNC m_pHandlingFunc;
    //处理函数参数
    void* m_pArg;

    //cfd对应的数据
    std::map<int, Server::PDATA>* m_pmapData;

    //待处理的任务队列
    std::queue<Server::PDATA>* m_pqueTask;

    //同步任务队列用
    std::mutex m_mutex;
    std::condition_variable m_cond;


    //请求头限制
    int m_nReqHeadLimit;
    //请求内容限制
    int m_nReqContentLimit;
};


#endif //RACOON_SERVER_H
